import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Random;

// 爆炸效果类
class Explosion {
    private int x;
    private int y;
    private int radius;
    private int maxRadius;
    private boolean active;

    public Explosion(int x, int y) {
        this.x = x;
        this.y = y;
        this.radius = 5;
        this.maxRadius = 30;
        this.active = true;
    }

    public boolean isActive() {
        return active;
    }

    public void update() {
        radius += 2;
        if (radius > maxRadius) {
            active = false;
        }
    }

    public void draw(Graphics g) {
        if (!active) return;

        Graphics2D g2d = (Graphics2D) g;
        g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,
                1.0f - (float)radius / maxRadius));

        g2d.setColor(Color.ORANGE);
        g2d.fillOval(x - radius, y - radius, radius * 2, radius * 2);

        g2d.setColor(Color.YELLOW);
        g2d.fillOval(x - radius/2, y - radius/2, radius, radius);

        g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1.0f));
    }
}

// 敌机子弹类
class EnemyBullet {
    private int x;
    private int y;
    private int speed;
    private static final int WIDTH = 5;
    private static final int HEIGHT = 15;

    public EnemyBullet(int x, int y) {
        this.x = x;
        this.y = y;
        this.speed = 7;
    }

    public int getX() {
        return x;
    }

    public int getY() {
        return y;
    }

    public void move() {
        y += speed;
    }

    public boolean isOutOfBounds() {
        return y > 600;
    }

    public void draw(Graphics g) {
        g.setColor(Color.RED);
        g.fillRect(x, y, WIDTH, HEIGHT);
    }

    public boolean hitFighter(Fighter fighter) {
        int fighterX = fighter.getX();
        int fighterY = fighter.getY();

        return x >= fighterX && x <= fighterX + 50 &&
                y >= fighterY && y <= fighterY + 50;
    }
}

// 抽象敌机类
abstract class Enemy {
    protected int x;
    protected int y;
    protected int width;
    protected int height;
    protected int speed;
    protected int scoreValue;
    protected int health;
    protected boolean alive;
    protected List<EnemyBullet> bullets;
    protected long lastShotTime;
    protected long shotInterval;

    public Enemy() {
        Random random = new Random();
        x = random.nextInt(770);
        y = 0;
        alive = true;
        bullets = new ArrayList<>();
        lastShotTime = System.currentTimeMillis();
    }

    public int getX() {
        return x;
    }

    public int getY() {
        return y;
    }

    public int getWidth() {
        return width;
    }

    public int getHeight() {
        return height;
    }

    public int getScoreValue() {
        return scoreValue;
    }

    public boolean isAlive() {
        return alive;
    }

    public void takeDamage() {
        health--;
        if (health <= 0) {
            alive = false;
        }
    }

    public List<EnemyBullet> getBullets() {
        return bullets;
    }

    public void shoot() {
        long currentTime = System.currentTimeMillis();
        if (currentTime - lastShotTime > shotInterval) {
            bullets.add(new EnemyBullet(x + width/2 - 2, y + height));
            lastShotTime = currentTime;
        }
    }

    public void updateBullets() {
        Iterator<EnemyBullet> it = bullets.iterator();
        while (it.hasNext()) {
            EnemyBullet bullet = it.next();
            bullet.move();
            if (bullet.isOutOfBounds()) {
                it.remove();
            }
        }
    }

    public abstract void move();

    public abstract boolean isOutOfBounds();

    public abstract boolean isHit(Bullet bullet);

    public abstract void draw(Graphics g);

    public abstract void drawBullets(Graphics g);
}

// 普通敌机
class NormalEnemy extends Enemy {
    public NormalEnemy() {
        super();
        width = 30;
        height = 30;
        speed = 5;
        scoreValue = 10;
        health = 1;
        shotInterval = 3000; // 3秒发射一次
    }

    @Override
    public void move() {
        y += speed;
        shoot();
        updateBullets();
    }

    @Override
    public boolean isOutOfBounds() {
        return y > 600;
    }

    @Override
    public boolean isHit(Bullet bullet) {
        return bullet.getX() >= x && bullet.getX() <= x + width &&
                bullet.getY() >= y && bullet.getY() <= y + height;
    }

    @Override
    public void draw(Graphics g) {
        if (!alive) return;

        g.setColor(Color.RED);
        g.fillOval(x, y, width, height);

        // 显示生命值
        if (health > 0) {
            g.setColor(Color.WHITE);
            g.setFont(new Font("Arial", Font.BOLD, 12));
            g.drawString("" + health, x + 10, y + 20);
        }
    }

    @Override
    public void drawBullets(Graphics g) {
        for (EnemyBullet bullet : bullets) {
            bullet.draw(g);
        }
    }
}

// 快速敌机
class FastEnemy extends Enemy {
    public FastEnemy() {
        super();
        width = 20;
        height = 20;
        speed = 8;
        scoreValue = 20;
        health = 1;
        shotInterval = 2000; // 2秒发射一次
    }

    @Override
    public void move() {
        y += speed;
        shoot();
        updateBullets();
    }

    @Override
    public boolean isOutOfBounds() {
        return y > 600;
    }

    @Override
    public boolean isHit(Bullet bullet) {
        return bullet.getX() >= x - 5 && bullet.getX() <= x + width + 5 &&
                bullet.getY() >= y - 5 && bullet.getY() <= y + height + 5;
    }

    @Override
    public void draw(Graphics g) {
        if (!alive) return;

        g.setColor(Color.MAGENTA);
        g.fillRect(x, y, width, height);
        g.setColor(Color.WHITE);
        g.setFont(new Font("Arial", Font.BOLD, 12));
        g.drawString("F", x + 5, y + 15);
    }

    @Override
    public void drawBullets(Graphics g) {
        for (EnemyBullet bullet : bullets) {
            bullet.draw(g);
        }
    }
}

// 大型敌机
class BigEnemy extends Enemy {
    public BigEnemy() {
        super();
        width = 60;
        height = 60;
        speed = 3;
        scoreValue = 50;
        health = 3;
        shotInterval = 1500; // 1.5秒发射一次
    }

    @Override
    public void move() {
        y += speed;
        shoot();
        updateBullets();
    }

    @Override
    public boolean isOutOfBounds() {
        return y > 600;
    }

    @Override
    public boolean isHit(Bullet bullet) {
        return bullet.getX() >= x && bullet.getX() <= x + width &&
                bullet.getY() >= y && bullet.getY() <= y + height;
    }

    @Override
    public void draw(Graphics g) {
        if (!alive) return;

        g.setColor(Color.BLUE);
        g.fillRoundRect(x, y, width, height, 15, 15);

        // 显示生命值
        g.setColor(Color.WHITE);
        g.setFont(new Font("Arial", Font.BOLD, 16));
        g.drawString("B", x + 20, y + 35);

        // 绘制生命值条
        g.setColor(Color.GREEN);
        int healthBarWidth = (width - 10) * health / 3;
        g.fillRect(x + 5, y + 5, healthBarWidth, 5);

        // 绘制生命值条边框
        g.setColor(Color.WHITE);
        g.drawRect(x + 5, y + 5, width - 10, 5);
    }

    @Override
    public void drawBullets(Graphics g) {
        for (EnemyBullet bullet : bullets) {
            bullet.draw(g);
        }
    }
}

// 战机类
class Fighter {
    private int x;
    private int y;
    private int health;
    private boolean invincible;
    private long invincibleEndTime;
    private static final long INVINCIBLE_DURATION = 2000; // 无敌时间2秒

    public Fighter() {
        x = 375;
        y = 550;
        health = 3;
        invincible = false;
    }

    public int getX() {
        return x;
    }

    public int getY() {
        return y;
    }

    public int getHealth() {
        return health;
    }

    public boolean isInvincible() {
        return invincible && System.currentTimeMillis() < invincibleEndTime;
    }

    public void setInvincible() {
        invincible = true;
        invincibleEndTime = System.currentTimeMillis() + INVINCIBLE_DURATION;
    }

    public void takeDamage() {
        if (!isInvincible() && health > 0) {
            health--;
            setInvincible();
        }
    }

    public void reset() {
        x = 375;
        y = 550;
        health = 3;
        invincible = false;
    }

    public void moveLeft() {
        if (x > 0) {
            x -= 10;
        }
    }

    public void moveRight() {
        if (x < 750) {
            x += 10;
        }
    }

    public void draw(Graphics g) {
        // 无敌状态闪烁效果
        if (isInvincible() && (System.currentTimeMillis() / 100) % 2 == 0) {
            return;
        }

        g.setColor(Color.GREEN);
        int[] xPoints = {x, x + 25, x + 50};
        int[] yPoints = {y + 50, y, y + 50};
        g.fillPolygon(xPoints, yPoints, 3);

        // 绘制驾驶舱
        g.setColor(Color.CYAN);
        g.fillOval(x + 15, y + 15, 20, 20);
    }

    public void drawHealth(Graphics g) {
        g.setColor(Color.WHITE);
        g.setFont(new Font("Arial", Font.BOLD, 20));
        g.drawString("HP: ", 20, 80);

        for (int i = 0; i < health; i++) {
            g.setColor(Color.RED);
            g.fillRect(70 + i * 30, 65, 20, 20);
        }
    }
}

// 子弹类
class Bullet {
    private int x;
    private int y;
    private static final int WIDTH = 5;
    private static final int HEIGHT = 20;
    private int speed;

    public Bullet(int x, int y) {
        this.x = x + 22;
        this.y = y;
        this.speed = 15;
    }

    public int getX() {
        return x;
    }

    public int getY() {
        return y;
    }

    public void move() {
        y -= speed;
    }

    public boolean isOutOfBounds() {
        return y < 0;
    }

    public void draw(Graphics g) {
        g.setColor(Color.YELLOW);
        g.fillRect(x, y, WIDTH, HEIGHT);
    }
}

// 游戏面板类
class GamePanel extends JPanel implements ActionListener, Runnable {
    private Fighter fighter;
    private List<Bullet> bullets;
    private List<Enemy> enemies;
    private List<Explosion> explosions;
    private Timer timer;
    private Thread enemySpawnThread;
    private int score;
    private int level;
    private boolean gameOver;
    private boolean paused;
    private Random random;
    private long lastLevelUpTime;
    private static final long LEVEL_UP_INTERVAL = 30000; // 每30秒升一级

    public GamePanel() {
        fighter = new Fighter();
        bullets = new ArrayList<>();
        enemies = new ArrayList<>();
        explosions = new ArrayList<>();
        score = 0;
        level = 1;
        gameOver = false;
        paused = false;
        random = new Random();
        lastLevelUpTime = System.currentTimeMillis();

        timer = new Timer(20, this);
        timer.start();

        enemySpawnThread = new Thread(this);
        enemySpawnThread.start();

        addKeyListener(new KeyAdapter() {
            @Override
            public void keyPressed(KeyEvent e) {
                if (gameOver) {
                    if (e.getKeyCode() == KeyEvent.VK_R) {
                        resetGame();
                    }
                    return;
                }

                if (e.getKeyCode() == KeyEvent.VK_LEFT) {
                    fighter.moveLeft();
                } else if (e.getKeyCode() == KeyEvent.VK_RIGHT) {
                    fighter.moveRight();
                } else if (e.getKeyCode() == KeyEvent.VK_SPACE) {
                    if (!paused) {
                        bullets.add(new Bullet(fighter.getX(), fighter.getY()));
                    }
                } else if (e.getKeyCode() == KeyEvent.VK_P) {
                    paused = !paused;
                }
            }
        });
        setFocusable(true);
        setBackground(Color.BLACK);
    }

    private void resetGame() {
        fighter.reset();
        bullets.clear();
        enemies.clear();
        explosions.clear();
        score = 0;
        level = 1;
        gameOver = false;
        lastLevelUpTime = System.currentTimeMillis();
    }

    private void checkLevelUp() {
        long currentTime = System.currentTimeMillis();
        if (currentTime - lastLevelUpTime > LEVEL_UP_INTERVAL) {
            level++;
            lastLevelUpTime = currentTime;
        }
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);

        if (paused) {
            drawPauseScreen(g);
            return;
        }

        if (gameOver) {
            drawGameOverScreen(g);
            return;
        }

        fighter.draw(g);
        fighter.drawHealth(g);

        for (Bullet bullet : bullets) {
            bullet.draw(g);
        }

        for (Enemy enemy : enemies) {
            if (enemy.isAlive()) {
                enemy.draw(g);
                enemy.drawBullets(g);
            }
        }

        for (Explosion explosion : explosions) {
            explosion.draw(g);
        }

        g.setColor(Color.WHITE);
        g.setFont(new Font("Arial", Font.BOLD, 24));
        g.drawString("Score: " + score, 20, 40);

        g.setColor(Color.YELLOW);
        g.drawString("Level: " + level, 20, 110);

        // 绘制控制提示
        g.setColor(Color.GRAY);
        g.setFont(new Font("Arial", Font.PLAIN, 16));
        g.drawString("← → : Move   Space : Shoot   P : Pause   R : Restart", 20, 570);
    }

    private void drawPauseScreen(Graphics g) {
        g.setColor(new Color(0, 0, 0, 180));
        g.fillRect(0, 0, getWidth(), getHeight());

        g.setColor(Color.YELLOW);
        g.setFont(new Font("Arial", Font.BOLD, 48));
        g.drawString("PAUSED", 330, 250);

        g.setColor(Color.WHITE);
        g.setFont(new Font("Arial", Font.PLAIN, 24));
        g.drawString("Press P to resume", 320, 320);
    }

    private void drawGameOverScreen(Graphics g) {
        g.setColor(new Color(0, 0, 0, 180));
        g.fillRect(0, 0, getWidth(), getHeight());

        g.setColor(Color.RED);
        g.setFont(new Font("Arial", Font.BOLD, 48));
        g.drawString("GAME OVER", 280, 220);

        g.setColor(Color.YELLOW);
        g.setFont(new Font("Arial", Font.BOLD, 36));
        g.drawString("Final Score: " + score, 300, 280);

        g.setColor(Color.YELLOW);
        g.setFont(new Font("Arial", Font.BOLD, 36));
        g.drawString("Level: " + level, 340, 330);

        g.setColor(Color.WHITE);
        g.setFont(new Font("Arial", Font.PLAIN, 24));
        g.drawString("Press R to restart", 320, 400);
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        if (paused || gameOver) {
            repaint();
            return;
        }

        checkLevelUp();

        // 移动子弹
        Iterator<Bullet> bulletIt = bullets.iterator();
        while (bulletIt.hasNext()) {
            Bullet bullet = bulletIt.next();
            bullet.move();
            if (bullet.isOutOfBounds()) {
                bulletIt.remove();
            }
        }

        // 移动敌机
        Iterator<Enemy> enemyIt = enemies.iterator();
        while (enemyIt.hasNext()) {
            Enemy enemy = enemyIt.next();
            enemy.move();

            if (!enemy.isAlive() || enemy.isOutOfBounds()) {
                if (!enemy.isAlive()) {
                    explosions.add(new Explosion(enemy.getX() + enemy.getWidth()/2,
                            enemy.getY() + enemy.getHeight()/2));
                    score += enemy.getScoreValue();
                }
                enemyIt.remove();
            }
        }

        // 更新爆炸效果
        Iterator<Explosion> explosionIt = explosions.iterator();
        while (explosionIt.hasNext()) {
            Explosion explosion = explosionIt.next();
            explosion.update();
            if (!explosion.isActive()) {
                explosionIt.remove();
            }
        }

        // 检测子弹与敌机碰撞
        for (int i = bullets.size() - 1; i >= 0; i--) {
            Bullet bullet = bullets.get(i);
            boolean bulletHit = false;

            for (int j = enemies.size() - 1; j >= 0; j--) {
                Enemy enemy = enemies.get(j);
                if (enemy.isAlive() && enemy.isHit(bullet)) {
                    enemy.takeDamage();
                    bullets.remove(i);
                    bulletHit = true;

                    if (!enemy.isAlive()) {
                        explosions.add(new Explosion(enemy.getX() + enemy.getWidth()/2,
                                enemy.getY() + enemy.getHeight()/2));
                        score += enemy.getScoreValue();
                    }
                    break;
                }
            }

            if (bulletHit) break;
        }

        // 检测敌机子弹与战机碰撞
        for (Enemy enemy : enemies) {
            for (EnemyBullet enemyBullet : enemy.getBullets()) {
                if (enemyBullet.hitFighter(fighter)) {
                    fighter.takeDamage();
                    enemy.getBullets().remove(enemyBullet);

                    if (fighter.getHealth() <= 0) {
                        gameOver = true;
                    }
                    break;
                }
            }
        }

        // 检测战机与敌机碰撞
        for (Enemy enemy : enemies) {
            if (!enemy.isAlive()) continue;

            int fighterX = fighter.getX();
            int fighterY = fighter.getY();

            if (fighterX + 50 > enemy.getX() &&
                    fighterX < enemy.getX() + enemy.getWidth() &&
                    fighterY + 50 > enemy.getY() &&
                    fighterY < enemy.getY() + enemy.getHeight()) {

                fighter.takeDamage();
                enemy.takeDamage();

                if (enemy.isAlive()) {
                    explosions.add(new Explosion(enemy.getX() + enemy.getWidth()/2,
                            enemy.getY() + enemy.getHeight()/2));
                }

                if (fighter.getHealth() <= 0) {
                    gameOver = true;
                }
            }
        }

        repaint();
    }

    @Override
    public void run() {
        try {
            while (true) {
                if (paused || gameOver) {
                    Thread.sleep(100);
                    continue;
                }

                Thread.sleep(1000 - (level - 1) * 50); // 随着等级提高，生成速度加快

                int randomNumber = random.nextInt(10);
                if (randomNumber < 3) {
                    enemies.add(new NormalEnemy());
                } else if (randomNumber < 8) {
                    enemies.add(new FastEnemy());
                } else {
                    enemies.add(new BigEnemy());
                }
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

// 主类
public class ThunderFighterGame {
    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            JFrame frame = new JFrame("雷霆战机");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.setSize(800, 600);
            frame.setResizable(true);
            GamePanel panel = new GamePanel();
            frame.add(panel);
            frame.setVisible(true);
        });
    }
}